package com.dhcc.bpm.modules.api.controller;

import cn.smallbun.screw.core.util.CollectionUtils;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dhcc.bpm.common.annotation.Log;
import com.dhcc.bpm.common.config.AppEmailConfig;
import com.dhcc.bpm.common.config.TemplateConfig;
import com.dhcc.bpm.common.constant.FilePathConstant;
import com.dhcc.bpm.common.enums.BusinessType;
import com.dhcc.bpm.common.enums.ConfigType;
import com.dhcc.bpm.common.json.JSON;
import com.dhcc.bpm.common.json.JSONObject;
import com.dhcc.bpm.common.redisMessage.RedisMessageSender;
import com.dhcc.bpm.common.utils.EmailUtils;
import com.dhcc.bpm.common.utils.ExcelUtil;
import com.dhcc.bpm.common.utils.FormatUtils;
import com.dhcc.bpm.common.utils.StringUtils;
import com.dhcc.bpm.modules.api.entity.*;
import com.dhcc.bpm.modules.api.service.*;
import com.dhcc.bpm.modules.api.vo.ApiVO;
import com.dhcc.bpm.modules.api.vo.BackserviceVO;
import com.dhcc.bpm.modules.common.entity.Plupload;
import com.dhcc.bpm.modules.common.entity.Upload;
import com.dhcc.bpm.modules.common.service.IPluploadService;
import com.dhcc.bpm.modules.cost.service.ICostRuleService;
import com.dhcc.bpm.modules.cost.vo.CostRuleVO;
import com.dhcc.bpm.modules.gateway.entity.Gateway;
import com.dhcc.bpm.modules.gateway.service.IGatewayRouteService;
import com.dhcc.bpm.modules.gateway.service.IGatewayService;
import com.dhcc.bpm.modules.gateway.vo.GatewayRouteVO;
import com.dhcc.bpm.modules.log.service.IGatewayLogDayService;
import com.dhcc.bpm.modules.log.service.IGatewayLogService;
import com.dhcc.bpm.modules.log.vo.AppApiViewVo;
import com.dhcc.bpm.modules.metadata.service.IMetadataService;
import com.dhcc.bpm.modules.metadata.vo.MetadataVO;
import com.dhcc.bpm.modules.orga.entity.App;
import com.dhcc.bpm.modules.orga.entity.AppApi;
import com.dhcc.bpm.modules.orga.service.IAppApiService;
import com.dhcc.bpm.modules.orga.service.IAppService;
import com.dhcc.bpm.modules.system.entity.Role;
import com.dhcc.bpm.modules.system.entity.User;
import com.dhcc.bpm.modules.system.service.IDictService;
import com.dhcc.bpm.modules.system.service.IRoleService;
import com.dhcc.bpm.modules.system.service.ISerialNumberService;
import com.dhcc.bpm.modules.system.service.IUserService;
import com.dhcc.bpm.modules.workflow.dto.ProcessStartDto;
import com.dhcc.bpm.modules.workflow.dto.TaskCommitDto;
import com.dhcc.bpm.modules.workflow.dto.TaskDto;
import com.dhcc.bpm.modules.workflow.service.IWorkFlowService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.log.annotation.ApiLog;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.*;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @ClassName ApiController
 * @Description api表 控制器
 * @Author daina
 * @Date 2020/2/25 13:14
 * @Version V1.0
 * @Copyright: 2020 东华软件 . All rights reserved.
 */
@RestController
@AllArgsConstructor
@NoArgsConstructor
@RequestMapping("bpm-api/opcapi")
public class ApiController extends BladeController {
    private static final Logger log = LoggerFactory.getLogger(ApiController.class);
    @Autowired
    private AppEmailConfig appEmailConfig;
    @Autowired
    private EmailUtils emailUtils;
    @Autowired
    private IApiService apiService;
    @Autowired
    private IIssueApiService issueApiService;
    @Autowired
    private ISerialNumberService serialNumberService;
    @Autowired
    private IProductApiService productApiService;
    @Autowired
    private IPluploadService pluploadService;
    @Autowired
    private IWorkFlowService iWorkFlowService;
    @Autowired
    private IBackserviceService backserviceService;
    @Autowired
    private IBaseProductService baseProductService;
    @Autowired
    private ISysService sysService;
    @Autowired
    private IUserService userService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IAppApiService appApiService;
    @Autowired
    private IAppService appService;
    @Autowired
    private ICostRuleService costRuleService;
    @Autowired
    private ITransformProtocolService transformProtocolService;
    @Autowired
    private IMetadataService metadataService;
    @Autowired
    private IDictService dictService;
    @Autowired
    private RedisMessageSender redisMessageSender;
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private IGatewayLogDayService gatewayLogDayService;
    @Autowired
    private IGatewayLogService gatewayLogService;
    @Autowired
    private IGatewayRouteService gatewayRouteService;
    @Autowired
    private IProductService productService;
    @Autowired
    private IGatewayService gatewayService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    private String path;

    @Value("${bpm.file-public-path}")
    public void setFileUploadPath(String publicPath) {
        path = publicPath + FilePathConstant.SQLPATH;
    }

    @Value("${bpm.approval.isSendMail}")
    private boolean isSendFlag;
    @Value("${bpm.approval.autoApproval}")
    private boolean autoApproval;

    /**
     * @return org.springblade.core.tool.api.R
     * @Description 自动生成服务编码
     * @Author daina
     * @Date 15:30 2020/12/04
     **/
    @PostMapping("/autoCreateCode")
    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "自动生成服务编码", notes = "传入app")
    @ApiLog("自动生成服务编码")
    @Log(title = "自动生成服务编码", businessType = BusinessType.OTHER)
    public R autoCreateCode(@ApiParam(value = "渠道号", required = true) @RequestParam String flag) {
        try {
            String appId = serialNumberService.generateSerialNumberByModelCode("opc_api");
            return R.data(appId);
        } catch (Exception e) {
            log.error("自动生成服务编码失败:{}", e);
            return R.status(false);
        }
    }

    /**
     * @param api
     * @return org.springblade.core.tool.api.R<com.dhcc.bpm.modules.api.entity.Api>
     * @Description 接口详情
     * @Author daina
     * @Date 14:34 2020/2/25
     **/
    @GetMapping("/detail")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "接口详情", notes = "传入api")
    @Log(title = "接口详情", businessType = BusinessType.SELECT)
    @ApiLog("接口详情")
    public R<ApiVO> detail(ApiVO api) {
        if (api.getId() == null) {
            return R.data(null);
        }
        Api detail = apiService.getOne(Condition.getQueryWrapper(api));
        if ("upgrade".equals(api.getType())) {
            detail.setXmlMsgConfig(null);
            detail.setJsonMsgConfig(null);
            detail.setKvMsgConfig(null);
            detail.setEfetMsgConfig(null);
            detail.setFixedMsgConfig(null);
            detail.setSepMsgConfig(null);
            detail.setXmlMsgId(null);
            detail.setEfetMsgId(null);
            detail.setBusId(null);
            detail.setMsgConfigId(null);
            detail.setXmlMsgUrl(null);
        }
        Plupload plupload = null;
        if (detail == null) {
            return R.data(null);
        }
        if (detail.getBusId() != null) {
            plupload = pluploadService.getById(detail.getBusId());
        }
        ApiVO apiVO = new ApiVO();
        BeanUtil.copy(detail, apiVO);
        if (detail.getCreateUser() != null) {
            //查用户名
            User user = userService.getById(detail.getCreateUser());
            if (user != null) {
                apiVO.setUserName(user.getRealName());
            }
        }
        if (detail.getBackserviceId() != null) {
            BaseProduct baseProduct = baseProductService.getById(detail.getBackserviceId());
            if (baseProduct != null) {
                apiVO.setBaseProductName(baseProduct.getProductName());
                //查出来所属系统名称
                Long sysId = baseProduct.getOpcSysId();
                Sys sys = sysService.selectBySysId(sysId);
                apiVO.setSysName(sys.getSysName());
            }
        }
        if (detail.getAtomicServiceId() != null) {
            Backservice backservice = backserviceService.getById(detail.getAtomicServiceId());
            if (backservice != null) {
                apiVO.setBackserviceName(backservice.getBackserviceName());
            }
        }

//        if (detail.getOpcGatewayId() != null) {
//            Gateway gateway = gatewayService.getById(detail.getOpcGatewayId());
//            if (gateway != null) {
//                apiVO.setGatewayName(gateway.getGatewayName());
//            }
//        }
//        if (detail.getOpcGatewayIdTest() != null) {
//            Gateway gatewayTest = gatewayService.getById(detail.getOpcGatewayIdTest());
//            if (gatewayTest != null) {
//                apiVO.setGatewayNameTest(gatewayTest.getGatewayName());
//            }
//        }
//
        if (plupload != null) {
            apiVO.setFileFullPath(plupload.getFileFullpath());
            apiVO.setStorageType(plupload.getStorageType());
            apiVO.setFileRealname(plupload.getFileRealname());
        }
        if (null != detail.getMsgConfigId() && -1 != detail.getMsgConfigId()) {
            plupload = pluploadService.getById(detail.getMsgConfigId());
            if (plupload != null) {
                apiVO.setConfigFileFullPath(plupload.getFileFullpath());
                apiVO.setConfigStorageType(plupload.getStorageType());
                apiVO.setConfigFileRealname(plupload.getFileRealname());
            }
        }
        if (null != detail.getEfetMsgId() && -1 != detail.getEfetMsgId()) {
            plupload = pluploadService.getById(detail.getEfetMsgId());
            if (plupload != null) {
                apiVO.setEfetMsgFullPath(plupload.getFileFullpath());
                apiVO.setEfetMsgStorageType(plupload.getStorageType());
                apiVO.setEfetMsgRealname(plupload.getFileRealname());
            }
        }
        if (null != detail.getXmlMsgId() && -1 != detail.getXmlMsgId()) {
            plupload = pluploadService.getById(detail.getXmlMsgId());
            if (plupload != null) {
                apiVO.setXmlMsgFullPath(plupload.getFileFullpath());
                apiVO.setXmlMsgStorageType(plupload.getStorageType());
                apiVO.setXmlMsgRealname(plupload.getFileRealname());
            }
        }
        // 报文配置文件 Xml add 2021-01-11
        if (null != detail.getXmlMsgConfig() && -1 != detail.getXmlMsgConfig()) {
            plupload = pluploadService.getById(detail.getXmlMsgConfig());
            if (plupload != null) {
                apiVO.setXmlFileFullPath(plupload.getFileFullpath());
                apiVO.setXmlFileRealname(plupload.getFileRealname());
            }
        }
        // 报文配置文件 Json add 2021-01-11
        if (null != detail.getJsonMsgConfig() && -1 != detail.getJsonMsgConfig()) {
            plupload = pluploadService.getById(detail.getJsonMsgConfig());
            if (plupload != null) {
                apiVO.setJsonFileFullPath(plupload.getFileFullpath());
                apiVO.setJsonFileRealname(plupload.getFileRealname());
            }
        }
        // 报文配置文件 Kv add 2021-01-11
        if (null != detail.getKvMsgConfig() && -1 != detail.getKvMsgConfig()) {
            plupload = pluploadService.getById(detail.getKvMsgConfig());
            if (plupload != null) {
                apiVO.setKvFileFullPath(plupload.getFileFullpath());
                apiVO.setKvFileRealname(plupload.getFileRealname());
            }
        }
        // 报文配置文件 Efet add 2021-01-11
        if (null != detail.getEfetMsgConfig() && -1 != detail.getEfetMsgConfig()) {
            plupload = pluploadService.getById(detail.getEfetMsgConfig());
            if (plupload != null) {
                apiVO.setEfetFileFullPath(plupload.getFileFullpath());
                apiVO.setEfetFileRealname(plupload.getFileRealname());
            }
        }
        // 报文配置文件 Fixed add 2021-01-11
        if (null != detail.getFixedMsgConfig() && -1 != detail.getFixedMsgConfig()) {
            plupload = pluploadService.getById(detail.getFixedMsgConfig());
            if (plupload != null) {
                apiVO.setFixedFileFullPath(plupload.getFileFullpath());
                apiVO.setFixedFileRealname(plupload.getFileRealname());
            }
        }
        // 报文配置文件 Sep add 2021-01-11
        if (null != detail.getSepMsgConfig() && -1 != detail.getSepMsgConfig()) {
            plupload = pluploadService.getById(detail.getSepMsgConfig());
            if (plupload != null) {
                apiVO.setSepFileFullPath(plupload.getFileFullpath());
                apiVO.setSepFileRealname(plupload.getFileRealname());
            }
        }

        if (detail != null && null != detail.getId()) {
            TransformProtocol transformProtocol = transformProtocolService.getByAPiId(detail.getId());
            apiVO.setTransformProtocol(transformProtocol);
        }
        return R.data(apiVO);


    }

    /**
     * @param api
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 根据产品ID查询接口列表
     * @Author daina
     * @Date 9:26 2020/3/26
     **/
    @GetMapping("/listByProductId")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "根据产品ID查询接口列表", notes = "传入api")
    @Log(title = "根据产品ID查询接口列表", businessType = BusinessType.SELECT)
    @ApiLog("根据产品ID查询接口列表")
    public R<IPage<ApiVO>> listByProductId(ApiVO api, Query query) {
        IPage<ApiVO> page = apiService.listByProductId(Condition.getPage(query), api);

        return R.data(page);
    }

    /**
     * @param
     * @return com.dhcc.bpm.common.json.JSONObject
     * @Author wjh
     * @Date 2020年12月1日16:03:19
     **/
    @GetMapping("/selectApiName")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "api关联查询", notes = "无参")
    @ApiLog("api名关联查询")
    @Log(title = "api名关联查询", businessType = BusinessType.SELECT)
    public JSONObject selectApiName() {
        JSONObject object = new JSONObject();
        object.put("success", true);
        object.put("names", apiService.selectApiName());
        return object;
    }

    /**
     * @param api
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 分页 api表
     * @Author daina
     * @Date 14:34 2020/2/25
     **/
    @GetMapping("/list")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "分页", notes = "传入api")
    @Log(title = "分页查询接口", businessType = BusinessType.SELECT)
    @ApiLog("分页查询接口")
    public R<IPage<ApiVO>> list(ApiVO api, Query query) {
        IPage<ApiVO> page;
        if (api.getSysId() != null) {
            //sys对应的所有api---------系统页面查api列表
            List<Long> apiIds = apiService.getApiIdsBySysId(api.getSysId());
            if (CollectionUtils.isEmpty(apiIds)) {
                //没有对应的api
                R r = new R();
                r.setMsg("没有匹配的api列表");
                r.setCode(200);
                r.setData(null);
                return r;
            }
            ApiVO api2 = new ApiVO();
            BeanUtils.copyProperties(api, api2);
            api2.setApiId(null);
            api2.setApiIds(apiIds);
            page = apiService.listInfo(Condition.getPage(query), api2);
        } else if (api.getOpcProductId() != null) {
            //应用产品对应的所有api---------应用产品页面查api列表
            List<Long> apiIds = apiService.getApiIdsBySysId(api.getSysId());
            if (CollectionUtils.isEmpty(apiIds)) {
                //没有对应的api
                R r = new R();
                r.setMsg("没有匹配的api列表");
                r.setCode(200);
                r.setData(null);
                return r;
            }
            ApiVO api2 = new ApiVO();
            BeanUtils.copyProperties(api, api2);
            api2.setApiId(null);
            api2.setApiIds(apiIds);

            page = apiService.listInfo(Condition.getPage(query), api2);
        } else {
            //基础产品传backserviceId就行
            page = apiService.listInfo(Condition.getPage(query), api);
        }


        // 统计信息  (响应次数、响应成功率、响应时间)
        if (page.getRecords() != null && page.getRecords().size() > 0) {
            for (ApiVO apiVO : page.getRecords()) {
                AppApiViewVo appApiViewVo = new AppApiViewVo();
                appApiViewVo.setApiId(apiVO.getApiCode());
                appApiViewVo.setEnv("0"); // 环境标志  0-生产环境
                AppApiViewVo apiCountData = gatewayLogDayService.apiCount(appApiViewVo);
                if (apiCountData != null) {
                    DecimalFormat df = new DecimalFormat("0.00");//格式化小数
                    // 求成功率
                    String successRateStr = "0.00";
                    double successRate = 0.00;
                    if (apiCountData.getRequestNum() != 0) {
                        successRate = (double) apiCountData.getSuccessNum() / apiCountData.getRequestNum() * 100;
                        successRateStr = FormatUtils.doubleFormat(successRate);
                    }

                    // 平均响应时间
                    double avgResTime = 0.00;
                    if (apiCountData.getLineNum() != 0) {
                        avgResTime = Double.valueOf(df.format(apiCountData.getResponseTime() / apiCountData.getLineNum()));
                    }

                    apiVO.setNum(apiCountData.getRequestNum());
                    apiVO.setSuccessNum(apiCountData.getSuccessNum());
                    apiVO.setSuccessRate(successRateStr + "%");
                    apiVO.setResponseTime(avgResTime);
                }
            }
        }
        return R.data(page);
    }

    @PostMapping("/download")
    public void download(ApiVO api, HttpServletResponse response) {
        int pagenum = 1;
        List<ApiVO> ApiVOlist = new ArrayList<>();
        while (true) {
            Query query = new Query();
            query.setCurrent(pagenum++);
            query.setSize(10);

            IPage<ApiVO> page = apiService.listInfo(Condition.getPage(query), api);
            // 统计信息  (响应次数、响应成功率、响应时间)
            if (page.getRecords() != null && page.getRecords().size() > 0) {
                for (ApiVO apiVO : page.getRecords()) {
                    AppApiViewVo appApiViewVo = new AppApiViewVo();
                    appApiViewVo.setApiId(apiVO.getApiCode());
                    appApiViewVo.setEnv("0"); // 环境标志  0-生产环境
                    AppApiViewVo apiCountData = gatewayLogDayService.apiCount(appApiViewVo);
                    if (apiCountData != null) {
                        DecimalFormat df = new DecimalFormat("0.00");//格式化小数
                        // 求成功率
                        String successRateStr = "0.00";
                        double successRate = 0.00;
                        if (apiCountData.getRequestNum() != 0) {
                            successRate = (double) apiCountData.getSuccessNum() / apiCountData.getRequestNum() * 100;
                            successRateStr = FormatUtils.doubleFormat(successRate);
                        }

                        // 平均响应时间
                        double avgResTime = 0.00;
                        if (apiCountData.getLineNum() != 0) {
                            avgResTime = Double.valueOf(df.format(apiCountData.getResponseTime() / apiCountData.getLineNum()));
                        }

                        apiVO.setNum(apiCountData.getRequestNum());
                        apiVO.setSuccessNum(apiCountData.getSuccessNum());
                        apiVO.setSuccessRate(successRateStr + "%");
                        apiVO.setResponseTime(avgResTime);
                    }
                }
                ApiVOlist.addAll(page.getRecords());
            } else {
                break;
            }
        }

        ExcelUtil<ApiVO> util = new ExcelUtil<ApiVO>(ApiVO.class);
        util.exportExcel(ApiVOlist, "API发布信息表", response);
    }

    /**
     * @param api
     * @param bladeUser
     * @return org.springblade.core.tool.api.R<java.util.List < com.dhcc.bpm.modules.api.entity.Api>>
     * @Description 下拉api名称
     * @Author daina
     * @Date 14:34 2020/2/25
     **/
    @GetMapping("/select")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "下拉api名称", notes = "传入product")
    @Log(title = "下拉api名称", businessType = BusinessType.SELECT)
    @ApiLog("下拉api名称")
    public R<List<Api>> select(Api api, BladeUser bladeUser) {
        QueryWrapper<Api> queryWrapper = Condition.getQueryWrapper(api);
        List<Api> list = apiService.list((!bladeUser.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID)) ? queryWrapper.lambda().eq(Api::getTenantId, bladeUser.getTenantId()) : queryWrapper);
        return R.data(list);
    }

    /**
     * @param appApiViewVo
     * @param query
     * @param bladeUser
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.log.vo.AppApiViewVo>>
     * @Description 某一应用下所有api下拉框列表
     * @Author daina
     * @Date 14:34 2020/2/25
     **/
    @GetMapping("/selectAppApi")
    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "某一应用下所有api下拉框列表", notes = "传入product")
    @Log(title = "某一应用下所有api下拉框列表", businessType = BusinessType.SELECT)
    @ApiLog("某一应用下所有api下拉框列表")
    public R<IPage<AppApiViewVo>> selectAppApi(AppApiViewVo appApiViewVo, Query query, BladeUser bladeUser) {
        if (query == null) {
            query = new Query();
            query.setCurrent(1);
            query.setSize(10);
        }
        IPage<AppApiViewVo> pages;
        if (appApiViewVo != null && appApiViewVo.getAppId() != null && appApiViewVo.getAppId().equals("-1")) { // 查询产品下api
            appApiViewVo.setAppId(null);
            pages = apiService.selectProApiList(Condition.getPage(query), appApiViewVo); // 查询某一产品下所有接口并分页
        } else {
            pages = apiService.selectAppApiList(Condition.getPage(query), appApiViewVo); // 查询某一应用下所有接口并分页
        }
        return R.data(pages);
    }


    /**
     * @param api
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 自定义分页 api表
     * @Author daina
     * @Date 14:34 2020/2/25
     **/
    @GetMapping("/page")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "自定义分页 api表", notes = "传入api")
    @Log(title = "自定义分页 api表", businessType = BusinessType.SELECT)
    @ApiLog("自定义分页 api表")
    public R<IPage<ApiVO>> page(ApiVO api, Query query) {
        IPage<ApiVO> pages = apiService.selectApiPage(Condition.getPage(query), api);
        return R.data(pages);
    }

    /**
     * @param api
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 自定义分页 网关接口列表
     * @Author daina
     * @Date 14:33 2020/2/25
     **/
    @GetMapping("/selectProductApiList")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "传入api")
    @Log(title = "自定义分页 网关接口列表", businessType = BusinessType.SELECT)
    @ApiLog("自定义分页 网关接口列表")
    public R<IPage<ApiVO>> selectBaseProductApiList(ApiVO api, Query query) {
        IPage<ApiVO> pages = apiService.selectBaseProductApiList(Condition.getPage(query), api);
        return R.data(pages);
    }


    /**
     * @return
     * @Description 自定义分页 网关接口列表
     * @Author daina
     * @Date 14:33 2020/2/25
     **/
    @GetMapping("/makeApiSQL")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "生成数据字典建表sql", notes = "传入apiId")
    @Log(title = "生成数据字典建表sql", businessType = BusinessType.SELECT)
    @ApiLog("生成数据字典建表sql")
    public R<Object> makeApiSQL(@ApiParam(value = "主键集合", required = true) @RequestParam Long id) {
        //测试 opcApiIdReq 1265622158894276609
        try {
            Api api = apiService.getById(id);
            String tableName = api.getApiEname().toUpperCase();
            Query query = new Query();
            query.setCurrent(1).setSize(999);
            MetadataVO metadata = new MetadataVO();
            metadata.setOpcApiIdReq(id);
            List<MetadataVO> pages = metadataService.selectReqMetadataList(Condition.getPage(query), metadata).getRecords();

            if (pages.isEmpty()) {
                return R.fail("没有可用字段不能生成建表sql");
            }

            List<MetadataVO> metadataVOList = new ArrayList<>();


            for (MetadataVO metadataVO : pages) {
                metadataVO.setFieldCode(StringUtils.camel2under(metadataVO.getFieldCode()));
                metadataVOList.add(metadataVO);
            }


            String pathUrl = path + "/" + api.getApiCode();

            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("tableName", tableName);
            hashMap.put("columnList", metadataVOList);
            TemplateConfig.generate(pathUrl + "/apiORACLE.sql", hashMap, "/sql/ORACLE.ftl");


            metadataVOList = new ArrayList<>();
            for (MetadataVO metadataVO : pages) {
                metadataVO.setFieldCode(StringUtils.camel2under(metadataVO.getFieldCode()).toLowerCase());
                metadataVOList.add(metadataVO);
            }
            hashMap.put("tableName", tableName.toLowerCase());
            hashMap.put("columnList", metadataVOList);
            TemplateConfig.generate(pathUrl + "/apiMYSQL.sql", hashMap, "/sql/MYSQL.ftl");

            String res = "";
            try (BufferedReader bufferedReader = new BufferedReader(new FileReader(new File(pathUrl + "/apiORACLE.sql")))) {
                String thisLine = null;
                while ((thisLine = bufferedReader.readLine()) != null) {
                    res += thisLine;
                }
            } catch (IOException e) {
                log.error("异常信息：{}", e);
            }
            return R.data(res);
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }

    }

    /**
     * @param api
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 自定义分页 沙箱设置接口表
     * @Author daina
     * @Date 14:33 2020/2/25
     **/
    @GetMapping("/getApiListByProductId")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "传入api")
    @Log(title = "自定义分页 沙箱设置接口表", businessType = BusinessType.SELECT)
    @ApiLog("自定义分页 沙箱设置接口表")
    public R<IPage<ApiVO>> getApiListByProductId(ApiVO api, Query query) {
        IPage<ApiVO> pages = apiService.getApiListByProductId(Condition.getPage(query), api);
        return R.data(pages);
    }

    /**
     * @param api
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 自定义分页 沙箱实例接口表
     * @Author daina
     * @Date 14:33 2020/2/25
     **/
    @GetMapping("/getApiListByCaseId")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "传入api")
    @Log(title = "自定义分页 沙箱实例接口表", businessType = BusinessType.SELECT)
    @ApiLog("自定义分页 沙箱实例接口表")
    public R<IPage<ApiVO>> getApiListByCaseId(ApiVO api, Query query) {
        IPage<ApiVO> pages = apiService.getApiListByCaseId(Condition.getPage(query), api);
        return R.data(pages);
    }

    /**
     * @param api
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 自定义分页 沙箱实例接口表
     * @Author daina
     * @Date 14:33 2020/2/25
     **/
    @GetMapping("/getApiListByAppId")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "传入api")
    @Log(title = "自定义分页 沙箱实例接口表", businessType = BusinessType.SELECT)
    @ApiLog("自定义分页 沙箱实例接口表")
    public R<IPage<ApiVO>> getApiListByAppId(ApiVO api, Query query) {
        IPage<ApiVO> pages = apiService.getApiListByAppId(Condition.getPage(query), api);
        // 统计信息  (响应次数、响应成功率、响应时间)
        if (pages.getRecords() != null && pages.getRecords().size() > 0) {
            for (ApiVO apiVO : pages.getRecords()) {
                AppApiViewVo appApiViewVo = new AppApiViewVo();
                appApiViewVo.setApiId(apiVO.getApiCode());
                appApiViewVo.setAppId(api.getAppCode());
                appApiViewVo.setEnv(api.getEnv()); // 环境标志  0-生产环境 1--沙箱
                AppApiViewVo apiCountData = gatewayLogDayService.apiCount(appApiViewVo);
                if (apiCountData != null) {
                    DecimalFormat df = new DecimalFormat("0.00");//格式化小数
                    // 求成功率
                    String successRateStr = "0.00";
                    double successRate = 0.00;
                    if (apiCountData.getRequestNum() != 0) {
                        successRate = (double) apiCountData.getSuccessNum() / apiCountData.getRequestNum() * 100;
                        successRateStr = FormatUtils.doubleFormat(successRate);
                    }

                    // 平均响应时间
                    double avgResTime = 0.00;
                    if (apiCountData.getLineNum() != 0) {
                        avgResTime = Double.valueOf(df.format(apiCountData.getResponseTime() / apiCountData.getLineNum()));
                    }

                    apiVO.setNum(apiCountData.getRequestNum());
                    apiVO.setSuccessNum(apiCountData.getSuccessNum());
                    apiVO.setSuccessRate(successRateStr + "%");
                    apiVO.setResponseTime(avgResTime);
                }
            }
        }
        return R.data(pages);
    }

    /**
     * @param apiVO
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 查询机构/系统下API列表以及统计数
     * @Author Mdd
     * @Date 2020/3/7 17:42
     **/
    @GetMapping("/getApiListByOrgaId")
    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "查询机构/系统下API列表以及统计数", notes = "传入ids")
    @Log(title = "查询机构/系统下API列表以及统计数", businessType = BusinessType.SELECT)
    @ApiLog("查询机构/系统下API列表以及统计数")
    public R<IPage<ApiVO>> selectCount(ApiVO apiVO, Query query, BladeUser bladeUser) {
        IPage<ApiVO> apiPage = null;
        if (StringUtils.isNotEmpty(apiVO.getKind()) && "product".equals(apiVO.getKind())) { // 产品
            apiPage = apiService.selectProductApiList(Condition.getPage(query), apiVO);
            apiPage = gainApiCount(apiPage, apiVO.getEnv()); // 获取api统计信息
        } else if (StringUtils.isNotEmpty(apiVO.getKind()) && "sys".equals(apiVO.getKind())) { // 系统
            // 某一系统下API列表
            apiPage = apiService.selectSysApiList(Condition.getPage(query), apiVO);
            if (apiPage.getRecords() != null && apiPage.getRecords().size() > 0) {
                // 系统下产品集合
                List<Product> sysProlist = productService.syslist(apiVO.getSysId());

                for (ApiVO vo : apiPage.getRecords()) {
                    Long num = 0L, successNum = 0L, lineNum = 0L;
                    Double resposeTime = 0.00;

                    if (sysProlist != null && sysProlist.size() > 0) {
                        // 产品下API统计
                        for (Product proVO : sysProlist) {
                            Query query1 = new Query();
                            query1.setCurrent(1);
                            query1.setSize(999999);
                            AppApiViewVo appApiViewVo = new AppApiViewVo();
                            appApiViewVo.setProductId(proVO.getId().toString());
                            appApiViewVo.setEnv(apiVO.getEnv());
                            IPage<AppApiViewVo> oneProPage = gatewayLogDayService.selectProApiNum(Condition.getPage(query1), appApiViewVo);
                            if (oneProPage.getRecords() != null && oneProPage.getRecords().size() > 0) {
                                for (AppApiViewVo oneProApiCount : oneProPage.getRecords()) {
                                    if (oneProApiCount.getApiId().equals(vo.getApiCode())) { // 同一API进行统计
                                        num += oneProApiCount.getRequestNum();
                                        successNum += oneProApiCount.getSuccessNum();
                                        lineNum += oneProApiCount.getLineNum();
                                        resposeTime += oneProApiCount.getResponseTime();
                                    }
                                }
                            }
                        }
                    }
                    //成功率
                    double successRate = 0;
                    String successRateStr = "0.00%";
                    DecimalFormat df = new DecimalFormat("0.00");//格式化小数
                    if (num != 0) {
                        successRate = (double) successNum / num * 100;
                        successRateStr = FormatUtils.doubleFormat(successRate) + "%";
                    }

                    // 平均响应时间
                    if (lineNum != 0) {
                        resposeTime = Double.valueOf(df.format(resposeTime / lineNum));
                    }
                    vo.setNum(num);
                    vo.setSuccessNum(successNum);
                    vo.setSuccessRate(successRateStr);
                    vo.setResponseTime(resposeTime);

                }
            }
        } else {
            apiPage = gatewayLogService.selectOrgaApiCount(Condition.getPage(query), apiVO); //机构
            apiPage = dealApiCount(apiPage); // 求成功率和平均响应时间
        }

        return R.data(apiPage);
    }

    /**
     * @param apiPage
     * @return com.baomidou.mybatisplus.core.metadata.IPage<com.dhcc.bpm.modules.api.vo.ApiVO>
     * @Description 求成功率和平均响应时间
     * @Author Mdd
     * @Date 2020/3/7 12:50
     **/
    private IPage<ApiVO> dealApiCount(IPage<ApiVO> apiPage) {
        for (ApiVO apiVO : apiPage.getRecords()) {
            DecimalFormat df = new DecimalFormat("0.00");//格式化小数

            // 求成功率
            String successRateStr = "0.00%";
            double successRate = 0;
            if (apiVO.getNum() != 0) {
                successRate = (double) apiVO.getSuccessNum() / apiVO.getNum() * 100;//返回的是String类型
                successRateStr = FormatUtils.doubleFormat(successRate) + "%";
            }

            // 平均响应时间
            double avgResTime = 0.00;
            if (apiVO.getLineNum() != 0) {
                avgResTime = Double.valueOf(df.format(apiVO.getResponseTime() / apiVO.getLineNum()));
            }

            apiVO.setSuccessRate(successRateStr);
            apiVO.setResponseTime(avgResTime);
        }
        return apiPage;

    }

    /**
     * @param apiPage
     * @return com.baomidou.mybatisplus.core.metadata.IPage<com.dhcc.bpm.modules.api.vo.ApiVO>
     * @Description api 集合求统计信息
     * @Author Mdd
     * @Date 2020/3/7 12:45
     **/
    private IPage<ApiVO> gainApiCount(IPage<ApiVO> apiPage, String env) {
        // 统计信息  (响应次数、响应成功率、响应时间)
        if (apiPage.getRecords() != null && apiPage.getRecords().size() > 0) {
            for (ApiVO vo : apiPage.getRecords()) {
                AppApiViewVo appApiViewVo = new AppApiViewVo();
                appApiViewVo.setApiId(vo.getApiCode());
                appApiViewVo.setEnv(env);
                AppApiViewVo apiCountData = gatewayLogDayService.apiCount(appApiViewVo);
                if (apiCountData != null) {
                    DecimalFormat df = new DecimalFormat("0.00");//格式化小数
                    // 求成功率
                    String successRateStr = "0.00";
                    double successRate = 0.00;
                    if (apiCountData.getRequestNum() != 0) {
                        successRate = (double) apiCountData.getSuccessNum() / apiCountData.getRequestNum() * 100;//返回的是String类型
                        successRateStr = FormatUtils.doubleFormat(successRate);
                    }

                    // 平均响应时间
                    double avgResTime = 0.00;
                    if (apiCountData.getLineNum() != 0) {
                        avgResTime = Double.valueOf(df.format(apiCountData.getResponseTime() / apiCountData.getLineNum()));
                    }

                    vo.setNum(apiCountData.getRequestNum());
                    vo.setSuccessNum(apiCountData.getSuccessNum());
                    vo.setSuccessRate(successRateStr + "%");
                    vo.setResponseTime(avgResTime);
                }
            }
        }
        return apiPage;
    }

    /**
     * @param api
     * @return org.springblade.core.tool.api.R
     * @Description 新增 api表
     * @Author daina
     * @Date 14:33 2020/2/25
     **/
    @PostMapping("/save")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "新增", notes = "传入api")
    @Log(title = "新增api", businessType = BusinessType.INSERT)
    @ApiLog("新增api")
    public R save(@Valid @RequestBody Api api) throws Exception {
        return R.status(apiService.save(api));
    }

    @ApiLog("导入excel")
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "导入excel", notes = "sysNum")
    @Log(title = "导入excel", businessType = BusinessType.SELECT)
    @PostMapping("importexcel")
    public R importexcel(Plupload plupload, HttpServletRequest request) {
        String name = null;
        Upload upload = new Upload();
        upload.setRequest(request);
        Upload uploadEntity = pluploadService.getFile(upload);
        MultipartFile file = uploadEntity.getMultipartFile();
        name = file.getOriginalFilename();
        uploadEntity.setName(name);
        //本地上传
        String id = pluploadService.fileLocalUpload(plupload, upload, request).toString();
        Plupload newupload = pluploadService.selectById(Long.parseLong(id));
        try (InputStream inputStream = new FileInputStream(new File(path + "/" + newupload.getFileRealname()))) {
            ExcelUtil<Api> excelUtil = new ExcelUtil<Api>(Api.class);
            List<Api> list = excelUtil.importExcel("API发布信息表", inputStream);
            for (Api sys : list) {
                try {
                    apiService.save(sys);
                } catch (Exception e) {
                    log.error("数据库异常：{}", e);
                    if (e.getMessage().contains("for key 'sys_name_idx'") || e.getMessage().contains("ORA-00001")) {
                        continue;
                    } else {
                        return R.fail(500, "数据库异常");
                    }
                } finally {

                }
            }
            pluploadService.fileDelete(Long.parseLong(id));
        } catch (FileNotFoundException e) {
            log.error("异常信息：{}", e);
        } catch (Exception e) {
            log.error("异常信息：{}", e);
        }
        return R.success("导入成功");
    }

    /**
     * @param api
     * @return org.springblade.core.tool.api.R
     * @Description 生成 openapi3.0文档
     * @Author lijiacheng
     * @Date 14:33 2020/2/25
     **/
    @PostMapping("/generateApiDoc")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "生成openapi3.0文档", notes = "传入api")
    @Log(title = "生成 openapi3.0文档", businessType = BusinessType.SELECT)
    @ApiLog("生成 openapi3.0文档")
    public R generateApiDoc(@Valid @RequestBody Api api) throws Exception {
        try {
            api = apiService.getById(api.getId());
            JSONObject openapi = new JSONObject();
            //openapi版本
            openapi.put("openapi", "3.0.0");
            //API相关基本信息
            JSONObject info = new JSONObject();
            info.put("version", api.getApiVersion());
//            info.put("title", api.getApiName());
//            info.put("description", api.getDescribe() == null?"":api.getDescribe());
            info.put("title", "沙箱测试接口");
            info.put("description", "沙箱测试接口列表");
            openapi.put("info", info);
            //后端服务
            JSONObject.JSONArray servers = new JSONObject.JSONArray();
//            String [] urlList = serversUrl.split(",");
//            for(int i = 0; i< urlList.length ; i++){
//                JSONObject url = new JSONObject();
//                url.put("url", urlList[i]);
//                url.put("description", "沙箱测试服务器");
//                servers.add(i, url);
//            }
            Gateway gateway = gatewayService.getById(api.getOpcGatewayIdTest());
            JSONObject urls = new JSONObject();
            urls.put("url", "http://" + gateway.getGatewayIp() + ":" + gateway.getGatewayPort());
            urls.put("description", gateway.getGatewayName());
            servers.add(urls);
            openapi.put("servers", servers);
            //接口信息
            JSONObject paths = new JSONObject();
            //参数信息
            MetadataVO metadataVO = new MetadataVO();
            metadataVO.setOpcApiIdReq(api.getId());
            metadataVO.setOpcApiIdRes(api.getId());
            Query query = new Query();
            query.setCurrent(1);
            query.setSize(10000);
            List<MetadataVO> metadataVOListReq = metadataService.selectReqMetadataList(Condition.getPage(query), metadataVO).getRecords();
            List<MetadataVO> metadataVOListRes = metadataService.selectResMetadataList(Condition.getPage(query), metadataVO).getRecords();
            JSONObject.JSONArray parameters = new JSONObject.JSONArray();
            for (MetadataVO metadataVOReq : metadataVOListReq) {
                JSONObject param = new JSONObject();
                param.put("name", metadataVOReq.getFieldCode());
                param.put("in", "query");
                param.put("description", metadataVOReq.getDescribe() == null ? "" : metadataVOReq.getDescribe());
                param.put("required", true);
//                param.put("style","form");
                JSONObject schema = new JSONObject();
                String str2 = Pattern.compile("[^a-zA-Z]").matcher(dictService.getValue("data_type", String.valueOf(metadataVOReq.getFieldType()))).replaceAll("").toLowerCase().trim();
                schema.put("type", str2);
                param.put("schema", schema);
                parameters.add(param);
            }
            JSONObject type = new JSONObject();

            JSONObject.JSONArray tags = new JSONObject.JSONArray();
            tags.add(api.getApiName());
            type.put("tags", tags);
            type.put("description", api.getDescribe() == null ? "" : api.getDescribe());
            type.put("operationId", api.getApiCode());
            type.put("parameters", parameters);
            //拼接响应体
            JSONObject responses = new JSONObject();
            JSONObject resStatus = new JSONObject();
            JSONObject schema = new JSONObject();
            schema.put("$ref", "#/components/schemas/Api");
            JSONObject content = new JSONObject();
            JSONObject resType = new JSONObject();
            resType.put("schema", schema);
            String msgType = "JSON";
            if (api.getMessageType() != null) {
                msgType = dictService.getValue("gateway_message_type", String.valueOf(api.getMessageType()));
            }
            if (msgType.equals("JSON")) {
                content.put("application/json", resType);
            } else if (msgType.equals("XML")) {
                content.put("application/xml", resType);
            } else {
                content.put("application/json", resType);
            }
            resStatus.put("description", "");
            resStatus.put("content", content);
            responses.put("200", resStatus);
            type.put("responses", responses);
            JSONObject url = new JSONObject();

            String reqType = api.getRequestMethod() == null ? "post" : dictService.getValue("request_method", String.valueOf(api.getRequestMethod())).toLowerCase();
            //请求方式
            url.put(reqType, type);
            paths.put(api.getApiPath(), url);
            //存放公用组件,主要是响应返回参数
            JSONObject components = new JSONObject();
            JSONObject schemas = new JSONObject();
            JSONObject schemaName = new JSONObject();
            JSONObject properties = new JSONObject();
            for (MetadataVO metadataVORes : metadataVOListRes) {
                JSONObject param = new JSONObject();
                String str2 = Pattern.compile("[^a-zA-Z]").matcher(dictService.getValue("data_type", String.valueOf(metadataVORes.getFieldType()))).replaceAll("").toLowerCase().trim();
                param.put("type", str2);
                param.put("description", metadataVORes.getDescribe() == null ? "" : metadataVORes.getDescribe());
                properties.put(metadataVORes.getFieldCode(), param);
            }
            schemaName.put("properties", properties);
            schemas.put("Api", schemaName);
            components.put("schemas", schemas);

            openapi.put("paths", paths);
            openapi.put("components", components);
            Map maps = JSON.unmarshal(openapi.toString(), Map.class);
            String openapiPath = apiService.saveOpenapi(api.getApiCode(), maps);
            api.setOpenapiPath(openapiPath);
            apiService.saveOrUpdate(api);
        } catch (Exception e) {
            log.error("异常信息：{}", e);
            return R.status(false);
        }
        return R.status(true);
    }

    /**
     * @param api
     * @return org.springblade.core.tool.api.R
     * @Description 修改 api表
     * @Author daina
     * @Date 14:32 2020/2/25
     **/
    @PostMapping("/update")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "修改", notes = "传入api")
    @Log(title = "修改api", businessType = BusinessType.UPDATE)
    @ApiLog("修改api")
    public R update(@Valid @RequestBody Api api) {
        return R.status(apiService.updateById(api));
    }

    /**
     * @param api
     * @return org.springblade.core.tool.api.R
     * @Description 修改api状态
     * @Author daina
     * @Date 9:24 2020/3/26
     **/
    @PostMapping("/changeStatus")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "修改api状态", notes = "传入api")
    @Log(title = "修改api状态", businessType = BusinessType.UPDATE)
    @ApiLog("修改api状态")
    public R changeStatus(@Valid @RequestBody Api api) {
        CostRuleVO costRule = costRuleService.getByApiId(api.getId());
        if (null != costRule) {
            costRule.setRefreshFlag(0);
            costRule.setStatus(api.getApiStatus());
            costRuleService.updateById(costRule);
        }
        return R.status(apiService.updateById(api));
    }

    /**
     * @param api //     * @param transformProtocolListVO
     * @return org.springblade.core.tool.api.R
     * @Description 新增或修改 api表
     * @Author daina
     * @Date 14:32 2020/2/25
     **/
    @PostMapping("/submit")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "新增或修改", notes = "传入api")
    @Log(title = "新增或修改 api表", businessType = BusinessType.UPDATE)
    @ApiLog("新增或修改 api表")
    @Transactional(rollbackFor = Exception.class)
    public R submit(@Valid @RequestBody ApiVO api/*, @RequestBody TransformProtocolListVO transformProtocolListVO*/) {
        boolean bool = false;
        Api apiOld = null;
        //升级api，修改低版本api为已升级，不推荐
        if (api.getId() != null && "2".equals(api.getIsUpgrade())) {
            apiOld = new Api();
            apiOld.setId(api.getId());
            apiOld.setIsUpgrade("2");
            apiOld.setIsRecommend("2");
            api.setId(null);
            api.setIsUpgrade("3");
            api.setIsRecommend("1");
        }
        //刷新状态: 0：未刷新
        api.setIsRefresh("0");
        // 提交
        if (null == api.getId() || api.getId() <= 0) {
//            String code = serialNumberService.generateSerialNumberByModelCode("opc_api");
            String code = "";
            if (api.getServiceCode() != null) {
                code = api.getServiceCode();
            }
            if (api.getServiceSubCode() != null) {
                code = code + api.getServiceSubCode();
            }
            if ("".equals(code)) {
                code = serialNumberService.generateSerialNumberByModelCode("opc_api");
            }
            api.setApiCode(code);
            if (api.getServiceCode() != null) {
                api.setServiceCode(code);
            }
            api.setStatus(9);

            /*
            20200929 修改apiNum的生成方式
             */
            api.setApiNum(code);
//            if(!"2".equals(api.getIsUpgrade())){
//                //产品编号前两位+api类别+三位数
//                BaseProduct baseProducts = new BaseProduct();
//                baseProducts.setId(api.getBackserviceId());
//                List<BaseProduct> detailList = baseProductService.selectById(api.getBackserviceId());
//                BaseProduct detail = detailList.get(0);
//                //得到那三位数字
//                String code = serialNumberService.generateSerialNumberByModelCode(detail.getProductNum());
//                api.setApiNum(String.valueOf(detail.getProductNum()).substring(0,2)+api.getApiType()+code);
//            }
        }


        // 查询基础产品信息
        BaseProduct baseProduct = null;
        //修改api创建时获取基础产品编码错误问题 修改时间：20201024 18:02
//        if("1".equals(api.getDevVersion())){
        /**
         * 东航版本
         * api直接和基础产品关联
         */
        try {
            baseProduct = baseProductService.getById(api.getBackserviceId());
        } catch (Exception e) {
            log.error("数据库异常：{}", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.fail(500, "数据库异常");
        } finally {

        }

        if (baseProduct != null) {
            List<BackserviceVO> backService = backserviceService.getByBaseProductId(baseProduct.getId());
            if (backService.size() > 0) {
                for (BackserviceVO backserviceVO : backService) {
                    if (backserviceVO.getBackserviceName().equals(baseProduct.getProductName())) {
                        api.setAtomicServiceId(backserviceVO.getId());
                    }
                }

            }
        }

//        }else{
//            /*
//             * 银行版本
//             * api和后端服务关联   后端服务和基础产品关联
//             */
//            // 查询后端服务信息
//            Backservice backservice;
//            try {
//                backservice = backserviceService.getById(api.getAtomicServiceId());
//            } catch (Exception e) {
//                log.error("数据库异常：{}", e);
//                return R.fail(500, "数据库异常");
//            } finally {
//
//            }
//            if(backservice != null && backservice.getBaseProductId() != null){
//                try {
//                    baseProduct = baseProductService.getById(backservice.getBaseProductId());
//                } catch (Exception e) {
//                    log.error("数据库异常：{}", e);
//                    return R.fail(500, "数据库异常");
//                } finally {
//
//                }
//            }else {
//                try {
//                    baseProduct = baseProductService.getById(api.getBackserviceId());
//                } catch (Exception e) {
//                    log.error("数据库异常：{}", e);
//                    return R.fail(500, "数据库异常");
//                } finally {
//
//                }
//            }
//
//        }

        // 查询系统信息
        Sys sys = new Sys();
        try {
            if (null != baseProduct && null != baseProduct.getOpcSysId()) {
                sys = sysService.getById(baseProduct.getOpcSysId());
            }
        } catch (Exception e) {
            log.error("数据库异常：{}", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.fail(500, "数据库异常");
        } finally {

        }
        // 判断是否手动输入了路径信息
        if ("2".equals(api.getAutoApiPath()) && api.getApiPath() != null && !"".equals(api.getApiPath())) {
//            String path = api.getApiPath();
//            api.setApiPath(("/prod/" + path + "/V" + api.getApiVersion()).replaceAll("//", "/"));
//            api.setApiPathTest(("/sandbox/" + path + "/V" + api.getApiVersion()).replaceAll("//", "/"));
            api.setApiPathTest(api.getApiPath());
        } else {
            // 设置api路径 沙箱路径
            if (null != api.getApiNum()) {
                String sysUrl = "";
                String baseProjectUrl = "";
                if (null != sys.getIsUrl() && sys.getIsUrl() == 2) {
                    sysUrl = sys.getUrl();
                } else {
                    sysUrl = sys.getSysNum();
                }
                if (null != sys.getIsUrl() && baseProduct.getIsUrl() == 2) {
                    baseProjectUrl = baseProduct.getUrl();
                } else {
                    baseProjectUrl = baseProduct.getProductNum();
                }
                api.setApiPath(("/prod/" + sysUrl + "/" + baseProjectUrl + "/" + api.getApiNum() + "/V" + api.getApiVersion()).replaceAll("//", "/"));
                api.setApiPathTest(("/sandbox/" + sysUrl + "/" + baseProjectUrl + "/" + api.getApiNum() + "/V" + api.getApiVersion()).replaceAll("//", "/"));
            }
        }


        // 插入或更新api信息
        boolean result;
        try {
            result = apiService.saveOrUpdate(api);
            if (result && apiOld != null) {
                apiService.updateById(apiOld);
            }
        } catch (Exception e) {
            log.error("数据库异常：{}", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            if (e.getMessage().contains("for key 'api_name_idx'") || e.getMessage().contains("ORA-00001")) {
                return R.fail(500, "该版本的API已存在");
            }
            return R.fail(500, "数据库异常");
        } finally {

        }

        if (result) {
//            List<TransformProtocol> lists = transformProtocolListVO.getLists();
//            if (null != lists && lists.size() > 0) {
//                for (TransformProtocol transformProtocol : lists) {
//                    if (transformProtocol.getType() != 99) {
//                        transformProtocol.setApiId(api.getId());
//                        transformProtocolService.saveOrUpdate(transformProtocol);
//                    } else {
//                        transformProtocolService.removeById(transformProtocol);
//                    }
//                }
//            }
            return R.data(api);
        } else {
            return R.status(false);
        }
    }


    /**
     * @param ids
     * @return org.springblade.core.tool.api.R
     * @Description 删除api信息
     * @Author daina
     * @Date 15:12 2020/4/28
     **/
    @PostMapping("/remove")
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "删除api信息", notes = "传入ids")
    @Log(title = "删除api信息", businessType = BusinessType.DELETE)
    @ApiLog("删除api信息")
    @Transactional(rollbackFor = Exception.class)
    public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
        try {
            List<Long> list = Func.toLongList(ids);
            for (Long data : list) {
                ProductApi productApi = new ProductApi();
                productApi.setApiId(data);
                List<ProductApi> apiList = productApiService.listProductApi(productApi);
                if (apiList.size() > 0) {
                    return R.fail(267, "此APi存在关联的产品，不能删除!");
                }
                List<AppApi> appApiLists = appApiService.selectByApiId(data);
                if (appApiLists.size() > 0) {
                    return R.fail(267, "此APi存在关联的渠道，不能删除!");
                }
                //删除路由
                List<GatewayRouteVO> routeList = gatewayRouteService.getByApiId(data.toString());
                routeList.forEach(route -> gatewayRouteService.removeById(route.getId()));
            }
            //删除对应的工作流
            String[] arrayIds = ids.split(",");
            for (String id : arrayIds) {
                iWorkFlowService.deleteRelated("b", id);//API发布
                iWorkFlowService.deleteRelated("y", id);//API下线
            }
            //删除api
            apiService.deleteLogic(Func.toLongList(ids));
        } catch (Exception e) {
            log.error("异常信息：{}", e);
            //事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.fail(268, "api删除失败");
        } finally {

        }
        return R.status(true);
    }


    /**
     * @param apivo
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.entity.Api>>
     * @Description 根据产品ID查询接口
     * @Author daina
     * @Date 14:31 2020/2/25
     **/
    @GetMapping("/getByProductId")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "根据产品ID查询接口", notes = "ApiVO")
    @Log(title = "根据产品ID查询接口", businessType = BusinessType.SELECT)
    @ApiLog("根据产品ID查询接口")
    public R<IPage<ApiVO>> getByProductId(ApiVO apivo, Query query) {
        List<Integer> statusList = new ArrayList<>();
        Integer status = apivo.getStatus();
        if (null == status) {
            statusList.add(1);
            statusList.add(5);
            apivo.setStatusList(statusList);
        } else {
            char[] numbers = status.toString().toCharArray();
            for (char number : numbers) {
                statusList.add(number - '0');
            }
            apivo.setStatusList(statusList);
        }
        IPage<ApiVO> pages = apiService.ByProductId(Condition.getPage(query), apivo);
        return R.data(pages);
    }

    /**
     * @param apivo
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 查询收费接口
     * @Author daina
     * @Date 14:31 2020/2/25
     **/
    @GetMapping("/getCostApiByProductId")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "查询收费接口", notes = "ApiVO")
    @Log(title = "查询收费接口", businessType = BusinessType.SELECT)
    @ApiLog("查询收费接口")
    public R<IPage<ApiVO>> getCostApiByProductId(ApiVO apivo, Query query) {
        List<Integer> statusList = new ArrayList<>();
        Integer status = apivo.getStatus();
        if (null == status) {
            statusList.add(1);
            statusList.add(5);
            apivo.setStatusList(statusList);
        } else {
            char[] numbers = status.toString().toCharArray();
            for (char number : numbers) {
                statusList.add(number - '0');
            }
            apivo.setStatusList(statusList);
        }
        IPage<ApiVO> pages = apiService.getCostApiByProductId(Condition.getPage(query), apivo);
        return R.data(pages);
    }

    /**
     * @param apivo
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 查询应用接口
     * @Author daina
     * @Date 19:00 2020/3/23
     **/
    @GetMapping("/getApiByProductId")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "查询应用接口", notes = "ApiVO")
    @Log(title = "查询应用接口", businessType = BusinessType.SELECT)
    @ApiLog("查询应用接口")
    public R<IPage<ApiVO>> getApiByProductId(ApiVO apivo, Query query) {
        IPage<ApiVO> pages = apiService.getApiByProductId(Condition.getPage(query), apivo);
        return R.data(pages);
    }

    /**
     * @param apivo
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.api.vo.ApiVO>>
     * @Description 查询应用接口
     * @Author daina
     * @Date 19:00 2020/3/23
     **/
    @GetMapping("/getApiByAppId")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "查询应用接口", notes = "ApiVO")
    @Log(title = "查询应用接口", businessType = BusinessType.SELECT)
    @ApiLog("查询应用接口")
    public R<IPage<ApiVO>> getApiByAppId(ApiVO apivo, Query query) {
        App app = appService.getById(apivo.getOpcAppId());
        apivo.setAppCode(app.getAppId());
        if("2".equals(apivo.getEnv())){
            apivo.setAppCode(app.getTestAppId());
        }

        IPage<ApiVO> pages = apiService.getApiByAppId(Condition.getPage(query), apivo);
        return R.data(pages);
    }

    /**
     * @param api
     * @return org.springblade.core.tool.api.R
     * @Description 修改时删除图片
     * @Author daina
     * @Date 14:31 2020/2/25
     **/
    @PostMapping("/deleteImage")
    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "修改时删除图片", notes = "ApiVO")
    @Log(title = "修改时删除图片", businessType = BusinessType.DELETE)
    @ApiLog("修改时删除图片")
    public R deleteImage(@RequestBody Api api) {
        if (null != api.getBusId() && -1 != api.getBusId()) {
            pluploadService.fileDelete(api.getBusId());
            api.setBusId(-1L);
        } else if (null != api.getMsgConfigId() && -1 != api.getMsgConfigId()) {
            //若果使用基础产品公共报文则不删除文件表
            if(!"1".equals(api.getIsCommonConfig())){
                pluploadService.fileDelete(api.getMsgConfigId());
            }
            api.setMsgConfigId(-1L);
        }
        return R.status(apiService.updateById(api));
    }

    /**
     * @param processStartDto
     * @return org.springblade.core.tool.api.R
     * @Description API 发布申请
     * @Author daina
     * @Date 14:31 2020/2/25
     **/
    @PostMapping("/issueApi")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = " API 发布申请", notes = "ApiVO")
    @Log(title = " API 发布申请", businessType = BusinessType.INSERT)
    @ApiLog(" API 发布申请")
    public R issueApi(@RequestBody ProcessStartDto processStartDto) {
        R r = new R();
        List<Long> id = new ArrayList<Long>();
        id.add(processStartDto.getId());
        List<ApiVO> apiList = apiService.getListByIds(id);
        if (apiList != null && apiList.get(0).getIsCost() == 1) {
            List<CostRuleVO> costRuleList = costRuleService.getListByIds(id);
            if (costRuleList == null || costRuleList.size() == 0) {
                r.setSuccess(false);
                r.setMsg("发布失败，请先对收费的API设置收费规则");
                return r;
            }
        }

        String appId = processStartDto.getAppId() + String.valueOf(processStartDto.getId());
        processStartDto.setAppId(appId);
        // 调用发布流程接口
        JSONObject resJson = iWorkFlowService.start(processStartDto);
        // 发布流程成功
        if (resJson != null && resJson.getInt("code") == 200) {
            Api api = new Api();
            api.setId(processStartDto.getId());
            // 0 ：发布审核中
            api.setStatus(0);
            // 更新状态
            boolean updated = apiService.updateById(api);
            if (updated) {
                r.setSuccess(true);
                r.setMsg("API申请发布成功");
                return r;
            }
        }
        // 发布流程失败
        r.setSuccess(false);
        r.setMsg("API申请发布失败");
        return r;
    }

    /**
     * @param processStartDto
     * @return org.springblade.core.tool.api.R
     * @Description API 下线申请
     * @Author daina
     * @Date 14:30 2020/2/25
     **/
    @PostMapping("/offShelveApply")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = " API 下线申请", notes = "ApiVO")
    @Log(title = " API 下线申请", businessType = BusinessType.INSERT)
    @ApiLog(" API 下线申请")
    @Transactional(rollbackFor = Exception.class)
    public R offShelveApply(@RequestBody ProcessStartDto processStartDto, BladeUser bladeUser) {
        R r = new R();
        boolean isAdmin = false;
        //判断用户是不是 管理员，是的话 直接审批通过
        Role role = roleService.getById(bladeUser.getRoleId());
        if ("administrator".equals(role.getRoleAlias())) {
            //是管理员
            isAdmin = true;
        }
        if (processStartDto.getIds() == null) {
            processStartDto.setIds(Func.toLongList(processStartDto.getId().toString()));
        }

        StringBuilder name = new StringBuilder();
        for (int i = 0; i < processStartDto.getIds().size(); i++) {
            ProcessStartDto processStartDto2 = new ProcessStartDto();
            processStartDto2.setId(processStartDto.getIds().get(i));
            String appId = processStartDto.getAppId() + processStartDto.getIds().get(i);
            processStartDto2.setAppId(appId);
            processStartDto2.setProcessKey(processStartDto.getProcessKey());
            processStartDto2.setUserId(processStartDto.getUserId());
            processStartDto2.setWfParm(processStartDto.getWfParm());
            // 调用发布流程接口
            JSONObject resJson = iWorkFlowService.start(processStartDto2);
            // 发布流程成功
            if (resJson != null && resJson.getInt("code") == 200) {
                Api api = new Api();
                api.setId(processStartDto.getIds().get(i));
                // 5：下线待审批
                api.setStatus(5);
                boolean updated = apiService.updateById(api);
                if (updated) {
                    //api下线通知渠道联系人
                    if (isSendFlag) {
                        List<AppApi> list = appApiService.selectByApiId(api.getId());
                        for (AppApi appApi : list) {
                            App app = appService.getById(appApi.getOpcAppId());
                            if (app != null && app.getPrpEmail() != null) {
                                String mailTitle = appEmailConfig.getTitle() + "api下线通知";
                                String msg = "亲爱的用户您好！您订阅的API:" + api.getApiName() + " 已下线，详情请登录开放门户查看。对您造成的不便敬请谅解！";
                                emailUtils.sendEmail(mailTitle, app.getPrpEmail(), mailTitle, msg);
                            }
                        }
                    }

                    if (autoApproval && isAdmin) {
                        //直接审批通过
                        JSONObject jsonObject = (JSONObject) resJson.get("data");
                        String EXECUTION_ID_ = jsonObject.getStr("instanceId");//EXECUTION_ID_字段
                        TaskDto taskDto = new TaskDto();
                        taskDto.setProcessKeys(EXECUTION_ID_);
                        taskDto = iWorkFlowService.findBytask(taskDto);
                        TaskCommitDto taskCommitDto = new TaskCommitDto();
                        taskCommitDto.setApiIds(new ArrayList<>());
                        taskCommitDto.setOpinionType("1");
                        taskCommitDto.setTaskId(taskDto.getId());
                        taskCommitDto.setUserId(bladeUser.getUserId().toString());
                        JSONObject json = iWorkFlowService.commit(taskCommitDto);
                        if (json != null && json.getInt("code") == 200) {
                            if ("chnl".equals(json.getStr("type"))) {
                                iWorkFlowService.refreshApp(json.getStr("id"));
                            }
                            if ("api".equals(json.getStr("type"))) {
                                iWorkFlowService.refreshApi(json.getStr("id"));
                            }
                            if (i != processStartDto.getIds().size() - 1) {
                                continue;
                            }
                        } else {
                            if (null != iWorkFlowService.getNameById(json)) {
                                name.append(iWorkFlowService.getNameById(json));
                                name.append(",");
                            }
                        }
                    }

                    if (i == processStartDto.getIds().size() - 1) {
                        //最后一条成功
                        r.setSuccess(true);
                        if (autoApproval && isAdmin) {
                            r.setMsg("下线申请提交成功,并自动审批");
                        }else {
                            r.setMsg("下线申请提交成功");
                        }

                        return r;
                    }


                } else {
                    //失败  直接结束
                    break;
                }
            } else {
                //失败  直接结束
//                break;
                r.setSuccess(false);
                r.setMsg(resJson.get("msg") == null ? "" : resJson.get("msg").toString());
                return r;
            }
        }
        if (StringUtils.isNotBlank(name)) {
            r.setSuccess(false);
            r.setMsg(name + "审批失败");
            return r;
        }
        r.setSuccess(false);
        r.setMsg("下线申请提交失败");
        return r;
    }

    /**
     * @param processStartDto
     * @return org.springblade.core.tool.api.R
     * @Description API 发布申请
     * @Author daina
     * @Date 14:30 2020/2/25
     **/
    @PostMapping("/issueApis")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = " API 发布申请", notes = "ApiVO")
    @Log(title = " API 发布申请", businessType = BusinessType.INSERT)
    @ApiLog(" API 发布申请")
    @Transactional(rollbackFor = Exception.class)
    public R issueApis(@RequestBody ProcessStartDto processStartDto, BladeUser bladeUser) {
        R r = new R();
        boolean isAdmin = false;
        //判断用户是不是 管理员，是的话 直接审批通过
        Role role = roleService.getById(bladeUser.getRoleId());
        if ("administrator".equals(role.getRoleAlias())) {
            //是管理员
            isAdmin = true;
        }
        try {
            List<ApiVO> apiList = apiService.getListByIds(processStartDto.getIds());
            List<CostRuleVO> costRuleList = costRuleService.getListByIds(processStartDto.getIds());
            for (Long apiId : processStartDto.getIds()) {
                int i = 0;
                for (ApiVO apiVO : apiList) {
                    if (apiVO.getId().longValue() == apiId.longValue()) {
                        if (apiVO.getIsCost() == 1) {
                            //此API是收费API
                            ++i;
                        }
                        break;
                    }
                }
                if (i > 0) {
                    if (costRuleList != null && costRuleList.size() > 0) {
                        int j = 0;
                        for (CostRuleVO costRule : costRuleList) {
                            if (Long.parseLong(costRule.getApiId()) == apiId) {
                                ++j;
                            }
                        }
                        if (j == 0) {
                            r.setSuccess(false);
                            r.setMsg("发布失败，请先对收费的API设置收费规则");
                            return r;
                        }
                    } else {
                        r.setSuccess(false);
                        r.setMsg("发布失败，请先对收费的API设置收费规则");
                        return r;
                    }
                }

            }

//            Long id = System.currentTimeMillis();
//            String appId = processStartDto.getAppId() + String.valueOf(id);
//            processStartDto.setAppId(appId);
//            // 调用发布流程接口
//            JSONObject resJson = iWorkFlowService.start(processStartDto);
//            if (resJson.getInt("code") == 200) {
//                List<Long> ids = processStartDto.getIds();
//                Api api = new Api();
//                IssueApi issueApi = new IssueApi();
//                for (Long apiId : ids) {
//                    api.setId(apiId);
//                    api.setStatus(0);
//                    apiService.updateById(api);
//                    issueApi.setId(id);
//                    issueApi.setApiId(apiId);
//                    issueApi.setApprovalStatus(0);
//                    issueApiService.insert(issueApi);
//                }
//           }
            List<Long> ids = processStartDto.getIds();
            String appid = processStartDto.getAppId();

            StringBuilder name = new StringBuilder();
            for (int j = 0; j < ids.size(); j++) {
                String appId = appid + ids.get(j);
                processStartDto.setAppId(appId);
                JSONObject resJson = iWorkFlowService.start(processStartDto);
                if (resJson.getInt("code") == 200) {
                    Api api = new Api();

                    api.setId(ids.get(j));
                    api.setStatus(0);
                    apiService.updateById(api);

                    issueApiService.deleteById(ids.get(j));
                    IssueApi issueApi = new IssueApi();
                    issueApi.setId(ids.get(j));
                    issueApi.setApiId(ids.get(j));
                    issueApi.setApprovalStatus(0);
                    issueApiService.insert(issueApi);

                    if (autoApproval && isAdmin) {
                        //直接审批通过
                        JSONObject jsonObject = (JSONObject) resJson.get("data");
                        String EXECUTION_ID_ = jsonObject.getStr("instanceId");//EXECUTION_ID_字段
                        TaskDto taskDto = new TaskDto();
                        taskDto.setProcessKeys(EXECUTION_ID_);
                        taskDto = iWorkFlowService.findBytask(taskDto);
                        TaskCommitDto taskCommitDto = new TaskCommitDto();
                        taskCommitDto.setApiIds(new ArrayList<>());
                        taskCommitDto.setOpinionType("1");
                        taskCommitDto.setTaskId(taskDto.getId());
                        taskCommitDto.setUserId(bladeUser.getUserId().toString());
                        JSONObject json = iWorkFlowService.commit(taskCommitDto);
                        if (json != null && json.getInt("code") == 200) {
                            if ("chnl".equals(json.getStr("type"))) {
                                iWorkFlowService.refreshApp(json.getStr("id"));
                            }
                            if ("api".equals(json.getStr("type"))) {
                                iWorkFlowService.refreshApi(json.getStr("id"));
                            }
                            continue;
                        } else {
                            if (null != iWorkFlowService.getNameById(json)) {
                                name.append(iWorkFlowService.getNameById(json));
                                name.append(",");
                            }
                        }
                    }

                } else {
                    r.setSuccess(false);
                    r.setMsg("API申请发布失败");
                    return r;
                }
                if (StringUtils.isNotBlank(name)) {
                    r.setSuccess(false);
                    r.setMsg(name + "审批失败");
                    return r;
                }

            }
        } catch (Exception e) {
            log.error("api发布发起审批异常:{}", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            r.setSuccess(false);
            r.setMsg("API申请发布失败");
            return r;
        }
        r.setSuccess(true);
        if (autoApproval && isAdmin) {
            r.setMsg("API申请发布成功,并自动审批成功");
        }else {
            r.setMsg("API申请发布成功");
        }

        return r;
    }

    /*
     * @Description updateApiWithTransformProtocol
     * @Author xushuaize
     * @Date 14:36 2020/3/10
     * @param api
     * @return org.springblade.core.tool.api.R
     * @ApiLog("更新API报文信息等字段接口")//接口描述内容
     * @Log(title = "更新API",businessType = BusinessType.DELETE)//接口描述内容，BusinessType：方法类型
     **/
    @PostMapping("/updateApiWithTransformProtocol")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "更新API报文信息等字段接口", notes = "ApiVO")
    @Log(title = "更新API报文信息等字段接口", businessType = BusinessType.INSERT)
    @ApiLog("更新API报文信息等字段接口")
    @Transactional(rollbackFor = Exception.class)
    public R updateApiWithTransformProtocol(@RequestBody Api api) {
        boolean bool = false;
        R r = new R();
        // 查询基础产品信息
        BaseProduct baseProduct;
        try {
            baseProduct = baseProductService.getById(api.getBackserviceId());
        } catch (Exception e) {
            log.info("数据库异常：{}", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.fail(500, "数据库异常");
        }
        if (baseProduct == null) {
            return R.fail(500, "基础产品不存在");
        }

        List<BackserviceVO> backService = backserviceService.getByBaseProductId(baseProduct.getId());
        if (backService.size() > 0) {
            for (BackserviceVO backserviceVO : backService) {
                if (backserviceVO.getBackserviceName().equals(baseProduct.getProductName())) {
                    api.setAtomicServiceId(backserviceVO.getId());
                }
            }
        }

        // 查询系统信息
        Sys sys = new Sys();
        try {
            if (null != baseProduct && null != baseProduct.getOpcSysId()) {
                sys = sysService.getById(baseProduct.getOpcSysId());
            }
        } catch (Exception e) {
            log.info("数据库异常：{}", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.fail(500, "数据库异常");
        }

        //修改apiNum
//        BaseProduct baseProducts = new BaseProduct();
//        baseProducts.setId(api.getBackserviceId());
//       List<BaseProduct> detailList = baseProductService.selectById(api.getBackserviceId());
//       BaseProduct detail = detailList.get(0);
//       Api oldApi = apiService.getById(api.getId());
//       String seqNum = oldApi.getApiNum().substring(oldApi.getApiNum().length() - 3, oldApi.getApiNum().length());
//       String apiNum = detail.getProductNum().substring(0,2) + api.getApiType() + seqNum;
//       api.setApiNum(apiNum);
        //api刷新状态: 0：未刷新
        api.setIsRefresh("0");
        String code = api.getServiceCode();
        if (null != api.getServiceSubCode()) {
            code = code + api.getServiceSubCode();
        }
        api.setApiCode(code);
        // 设置api路径 沙箱路径
        if ("1".equals(api.getAutoApiPath())) {
            String sysUrl = "";
            String baseProjectUrl = "";
            if (sys.getIsUrl() == 2) {
                sysUrl = sys.getUrl();
            } else {
                sysUrl = sys.getSysNum();
            }
            if (baseProduct.getIsUrl() == 2) {
                baseProjectUrl = baseProduct.getUrl();
            } else {
                baseProjectUrl = baseProduct.getProductNum();
            }
            api.setApiPath(("/prod/" + sysUrl + "/" + baseProjectUrl + "/" + api.getApiCode() + "/V" + api.getApiVersion()).replaceAll("//", "/"));
            api.setApiPathTest(("/sandbox/" + sysUrl + "/" + baseProjectUrl + "/" + api.getApiCode() + "/V" + api.getApiVersion()).replaceAll("//", "/"));


        } else {
//            Api apiData = apiService.getById(api.getId());
//           if (!apiData.getApiPath().equals(api.getApiPath())){
//               String path = api.getApiPath();
//               api.setApiPath(("/prod/" + path + "/V" + api.getApiVersion()).replaceAll("//", "/"));
//               api.setApiPathTest(("/sandbox/" + path + "/V" + api.getApiVersion()).replaceAll("//", "/"));
//           }
//           if (!apiData.getApiVersion().equals(api.getApiVersion())){
//               String path = api.getApiPath().replace("/prod/", "");
//               path = path.substring(0, path.indexOf("/V"));
//               api.setApiPath(("/prod/" + path + "/V" + api.getApiVersion()).replaceAll("//", "/"));
//               api.setApiPathTest(("/sandbox/" + path + "/V" + api.getApiVersion()).replaceAll("//", "/"));
//           }
            api.setApiPathTest(api.getApiPath());
//            if (!api.getApiPath().contains(api.getApiVersion())) {
//                //api版本变了
//                api.setApiPath(("/prod/" + api.getApiPath() + "/V" + api.getApiVersion()).replaceAll("//", "/"));
//            }
//            if (!api.getApiPathTest().contains(api.getApiVersion())) {
//                //api版本变了
//                api.setApiPathTest(("/sandbox/" + api.getApiPath() + "/V" + api.getApiVersion()).replaceAll("//", "/"));
//            }
        }

        Api apiData = apiService.getById(api.getId());

        bool = apiService.updateById(api);
        //修改api路由
//       if(bool){
//           List<GatewayRouteVO> routes = gatewayRouteService.getByApiId(api.getId().toString());
//           for(GatewayRouteVO route : routes){
//               if ("1".equals(route.getEnv())){
//                   route.setOpcGatewayId(api.getOpcGatewayId());
//                   route.setRouteConfig("[{\"predicateValue\":\"" + api.getApiPath() + "\",\"name\":\"Path\"}]");
//               }else{
//                   route.setOpcGatewayId(api.getOpcGatewayIdTest());
//                   route.setRouteConfig("[{\"predicateValue\":\"" + api.getApiPathTest() + "\",\"name\":\"Path\"}]");
//               }
//               gatewayRouteService.saveOrUpdate(route);
//           }
//       }


        List<GatewayRouteVO> routes = gatewayRouteService.getByApiId(api.getId().toString());
        //修改路由routeConfig字段
        if(!api.getApiPath().equals(apiData.getApiPath())){
            List<GatewayRouteVO> configRoutes = routes.stream().filter((GatewayRouteVO gatewayRoute) ->
                    gatewayRoute.getRouteConfig().indexOf("\"name\":\"Path\"") > -1)
                    .collect(Collectors.toList());
            configRoutes.forEach(gatewayRoute ->{
                JSONArray jsonArray = new JSONArray();
                JSONArray array = JSONArray.parseArray(gatewayRoute.getRouteConfig());
                Iterator iterator = array.stream().iterator();
                if (iterator.hasNext()){
                    com.alibaba.fastjson.JSONObject json = com.alibaba.fastjson.JSONObject.parseObject(iterator.next().toString());
                    if("Path".equals(json.getString("name"))){
                        String predicateValue = api.getApiPath();
                        if(!"1".equals(gatewayRoute.getEnv())){
                            predicateValue = api.getApiPathTest();
                        }
                        json.put("predicateValue", predicateValue.replace("//", "/"));
                        jsonArray.add(json);
                    }
                }
                gatewayRoute.setRouteConfig(jsonArray.toJSONString());
                gatewayRouteService.saveOrUpdate(gatewayRoute);
            });
        }
        //修改路由过滤器配置 && (!api.getIdentPath().equals(apiData.getIdentPath())
        //                || !"1".equals(apiData.getIsIdentPath()) )
        if("1".equals(api.getIsIdentPath()) && "1".equals(apiData.getIsIdentPath())
                && !api.getIdentPath().equals(apiData.getIdentPath()) ){
            routes = routes.stream().filter((GatewayRouteVO gatewayRoute) ->
                    gatewayRoute.getFilters().indexOf("\"name\":\"SetPath\"") > -1)
                    .collect(Collectors.toList());
            routes.forEach(gatewayRoute ->{
                JSONArray jsonArray = new JSONArray();
                JSONArray array = JSONArray.parseArray(gatewayRoute.getFilters());
                Iterator iterator = array.stream().iterator();
                if (iterator.hasNext()){
                    com.alibaba.fastjson.JSONObject json = com.alibaba.fastjson.JSONObject.parseObject(iterator.next().toString());
                    if("SetPath".equals(json.getString("name"))){
                        String filterValue = json.getString("filterValue");
                        if( filterValue.endsWith(apiData.getIdentPath())){
                            filterValue = filterValue.replace(apiData.getIdentPath(), api.getIdentPath());
                        }
                        json.put("filterValue", filterValue.replace("//", "/"));
                        jsonArray.add(json);
                    }
                }
                gatewayRoute.setFilters(jsonArray.toJSONString());
                gatewayRouteService.saveOrUpdate(gatewayRoute);
            });
        }else if("1".equals(api.getIsIdentPath()) && !"1".equals(apiData.getIsIdentPath())){
            routes.forEach(gatewayRoute ->{
                Backservice  backservice = backserviceService.getById(api.getAtomicServiceId());
                String filters = "[{\"filterValue\":\"" + "/" + api.getIdentPath() + "\",\"name\":\"SetPath\"}]";
                if(backservice != null && StringUtil.isNotBlank(backservice.getServicePath())
                        && !"/".equals(backservice.getServicePath())){
                    filters = "[{\"filterValue\":\"" + "/" + backservice.getServicePath() + "/" + api.getIdentPath() + "\",\"name\":\"SetPath\"}]";
                }
                gatewayRoute.setFilters(filters.replace("//", "/"));
                gatewayRouteService.saveOrUpdate(gatewayRoute);
            });
        }else if(!"1".equals(api.getIsIdentPath()) && "1".equals(apiData.getIsIdentPath())){
            routes = routes.stream().filter((GatewayRouteVO gatewayRoute) ->
                    gatewayRoute.getFilters().indexOf("\"name\":\"SetPath\"") > -1)
                    .collect(Collectors.toList());
            routes.forEach(gatewayRoute ->{
                JSONArray jsonArray = new JSONArray();
                JSONArray array = JSONArray.parseArray(gatewayRoute.getFilters());
                Iterator iterator = array.stream().iterator();
                if (iterator.hasNext()){
                    com.alibaba.fastjson.JSONObject json = com.alibaba.fastjson.JSONObject.parseObject(iterator.next().toString());
                    if("SetPath".equals(json.getString("name"))){
                        array.remove(json);
                    }
                }
                gatewayRoute.setFilters(array.toJSONString());
                gatewayRouteService.saveOrUpdate(gatewayRoute);
            });
        }

        //修改了基础产品  对应的api路由也要修改
        if (api.getBackserviceId() != null) {
            GatewayRouteVO gatewayRoute = new GatewayRouteVO();
            gatewayRoute.setBackServiceId(api.getBackserviceId().toString());
            gatewayRoute.setOpcApiId(api.getId().toString());
            gatewayRouteService.updateBackServiceIdByApiId(gatewayRoute);
        }
        r.setSuccess(apiService.updateApiWithTransformProtocol(api) && bool);
        r.setMsg("操作成功");
        return r;
    }

    /**
     * @param apiNum
     * @return java.util.List<com.dhcc.bpm.modules.api.vo.BaseProductVO>
     * @throws
     * @Description 编码判断是否重复
     * @Author xiafayu
     * @Date 2020/3/21 20:18
     **/
    @ApiLog("查询接口编码")
    @PostMapping("/selectBySysNum")
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "查询接口编码", notes = "sysNum")
    @Log(title = "查询接口编码", businessType = BusinessType.SELECT)
    public R selectBySysNum(@ApiParam(value = "接口编码", required = true) @RequestParam String apiNum) {
        List<ApiVO> list = apiService.selectBySysNum(apiNum);
        if (list.size() > 0) {
            return R.data(false);
        }
        return R.data(true);
    }


    @GetMapping("/callBackList")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "分页", notes = "传入orga")
    @ApiLog("分页 api下回调地址列表")
    @Log(title = "分页 api下回调地址列表", businessType = BusinessType.SELECT)
    public R<IPage<ApiVO>> callBackList(ApiVO api, Query query) {
        IPage<ApiVO> pages = apiService.callBackList(Condition.getPage(query), api);
        return R.data(pages);
    }

    /**
     * @param
     * @return org.springblade.core.tool.api.R<com.dhcc.bpm.modules.gateway.entity.GatewayRoute>
     * @Description 刷新产品配置
     * @Date 2019/11/27 15:02
     **/
    @ApiLog("刷新接口配置")
    @PostMapping("/refreshApi")
    @ApiOperationSupport(order = 8)
    @Log(title = "刷新接口配置", businessType = BusinessType.REFRESH)
    public R refreshApi() {
        try {
            String message = redisMessageSender.format(ConfigType.API.name(), "刷新接口配置");
            redisMessageSender.sendMessageToGateway(null, message);
//            String msg = redisMessageSender.format(ConfigType.RATELIMET.name(), "刷新接口限流配置");
//            redisMessageSender.sendMessageToGateway(null, msg);
            String route = redisMessageSender.format(ConfigType.ROUTE.name(), "刷新接口路由配置");
            redisMessageSender.sendMessageToGateway(null, route);
            return R.status(true);
        } catch (Exception e) {
            log.error("刷新产品配置失败:{}", e);
            return R.status(false);
        }
    }

    /**
     * @Description 推送消息给网关，通知网关重新拉取配置文件信息。
     * @Date 2020年7月21日10:20:05
     **/
    @ApiLog("刷新网关路由")
    @PostMapping("/refreshRoute")
    @ApiOperationSupport(order = 8)
    @Log(title = "刷新网关", businessType = BusinessType.REFRESH)
    public R refreshRoute() {
        try {
            String route = redisMessageSender.format(ConfigType.API.name(), "重新拉取配置文件信息");
            redisMessageSender.sendMessageToGateway(null, route);
            //更新api状态
            ApiVO api = new ApiVO();
            //是否刷新
            api.setIsRefresh("1");
            apiService.updateRefreshStatus(api);
            return R.status(true);
        } catch (Exception e) {
            log.error("刷新产品配置失败:{}", e);
            return R.status(false);
        }
    }

    @ApiLog("API信息-查询所有")
    @GetMapping("/listAllApis")
    @ApiOperationSupport(order = 9)
    @Log(title = "API信息-查询所有", businessType = BusinessType.SELECT)
    public R listAllApis() {
        return R.data(apiService.listAllApis());
    }

    @ApiLog("查询api关联渠道列表")
    @GetMapping("/queryAppList")
    @ApiOperationSupport(order = 10)
    @Log(title = "查询api关联渠道列表", businessType = BusinessType.SELECT)
    public R queryAppList(@ApiParam(value = "接口id", required = true) @RequestParam Long apiId,
                          @ApiParam(value = "应用产品id", required = true) @RequestParam Long productId,
                     @ApiParam(value = "环境", required = true) @RequestParam String env) {

       List<AppApi> appApiList = appApiService.selectByApiIdEnv(apiId, productId, env);
       List<String> appList = appApiList.stream().map(appApi -> appApi.getOpcAppId().toString()).collect(Collectors.toList());

        return R.data(appList);
    }


    @ApiLog("服务关联渠道保存")
    @PostMapping("/saveAppApiList")
    @ApiOperationSupport(order = 10)
    @Transactional(rollbackFor = Exception.class)
    @Log(title = "服务关联渠道保存", businessType = BusinessType.SELECT)
    public R saveAppApiList(@Valid @RequestBody com.alibaba.fastjson.JSONObject json) {
      String apiId = json.getString("apiId");
      String env = json.getString("env");
      String productId = json.getString("productId");
      String appListJson = JSONArray.toJSONString(json.get("appList"));
      List<String> appList = JSONArray.parseArray(appListJson, String.class);

      try {

          //插入新关联数据

          List<String> ids = new ArrayList<>();
          for (String appId : appList) {
              String id = appId.split("#")[0];
              //2是移除的数据不入库，1：新增，2：移除，3：不变
              if(!"3".equals(appId.split("#")[1])){
                  ids.add(id);
              }
              if("2".equals(appId.split("#")[1])){
                  //删除移除的数据
                  appApiService.deleteAppApi(apiId, id, env);
                  continue;
              }

              if("1".equals(appId.split("#")[1])){
                  AppApi appApi = new AppApi();
                  appApi.setOpcApiId(Long.valueOf(apiId));
                  appApi.setApprovalEnv(env);
                  appApi.setChangeStatus("1");
                  appApi.setOpcProductId(Long.valueOf(productId));
                  appApi.setValidStatus("1");
                  appApi.setExpSeq(stringRedisTemplate.opsForValue().get("expSeq"));
                  appApi.setOpcAppId(Long.valueOf(id));
                  appApi.setId(null);
                  if(!appApiService.save(appApi)){
                      TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                      return R.fail("保存数据失败");
                  }
              }

          }

          //刷新token权限
          refreshToken(ids, env);
      }catch (Exception e){
          log.error("api关联渠道保存失败：{}", e);
          TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
          return R.fail("保存数据失败");
      }

      return R.success("保存数据成功");
    }

    public void refreshToken(List<String> appIds, String env) {
        for (String appId : appIds){
            App app = appService.getById(appId);
            String appCode = app.getTestAppId();
            if("1".equals(env)){
                appCode = app.getAppId();
            }
            //刷新token
            Collection<OAuth2AccessToken> findTokensByClientId = tokenStore.findTokensByClientId(appCode);
            findTokensByClientId.forEach(p -> redisMessageSender.sendMessageToChannel("TOKEN", tokenStore.readAccessToken(p.getValue()).getValue()));

        }
    }
}
